package com.gaojiawei.multiThread11_ThreadPoolJDk;

import java.util.concurrent.*;

/**
 * user workstealing pool
 */
public class L05_WorkStealingPool {
    static int[] num = new int[100000000];

    static {
        for(int i = 0;i < num.length;i++){
            num[i] = (int)(Math.random()*1000);
        }
    }

    public static void main(String[] args) {
        //use single Thread to compute sum
        int sumSingleThread = 0;
        long beginSingleTime = System.currentTimeMillis();
        for(int i : num){
            sumSingleThread +=i;
        }
        long endSingleThreadTime = System.currentTimeMillis();
        long costSingleThreadTime = endSingleThreadTime - beginSingleTime;
        System.out.println("result of single thread is"+sumSingleThread+"cost time with"+costSingleThreadTime);

        //user work stealing pool to fork and join
        //when use fork join pool runnable and callable is not be recommended
        ForkJoinPool forkJoinPool = (ForkJoinPool)Executors.newWorkStealingPool();
        long beginTimeForkJoinPool = System.currentTimeMillis();
        ForkJoinTask<Integer> task = forkJoinPool.submit(new SumRecursiveTask(0, num.length - 1));
        Integer forkJoinPoolResult = task.join();
        long endTimeForkJoinPool = System.currentTimeMillis();
        long costTimeForkJoinPool = endTimeForkJoinPool - beginTimeForkJoinPool;
        System.out.println("result of fork join pool thread is"+forkJoinPoolResult+"cost time with "+costTimeForkJoinPool);

    }

    public static class SumRecursiveTask extends RecursiveTask<Integer>{

        private int start,end;

        private final int MAX_STRIDE = 100000000;

        SumRecursiveTask(int start,int end){
            this.start = start;
            this.end = end;
        }

        /**
         * in this method we should make a logic of task spliting and joining
         * @return
         */
        @Override
        protected Integer compute() {
            int sum = 0;
            int stride = end -start;
            if(stride < MAX_STRIDE){
                for(int i = start;i <= end;i++){
                    sum +=num[i];
                }
            }else {
                int mid = start + ((end - start)>>1);
                //create two task
                SumRecursiveTask leftTask = new SumRecursiveTask(start, mid);
                SumRecursiveTask rightTask = new SumRecursiveTask(mid + 1, end);

                //excute these two task
                leftTask.fork();
                rightTask.fork();

                //join result
                sum = leftTask.join()+rightTask.join();

            }
            return sum;

        }
    }


}
